#include "Demo.h"
#include "resource.h"
#include <windowsx.h>
//////////////////////////////////////////////////////////////////////////
// CDemoApp
//////////////////////////////////////////////////////////////////////////
CDemoApp::CDemoApp()
{

}

CDemoApp::~CDemoApp()
{

}

bool CDemoApp::InitInstance()
{
	m_pMainWnd = new CDemoWnd();
	m_pMainWnd->ShowWindow(SW_SHOW);
																   
	return true;
}

//////////////////////////////////////////////////////////////////////////
// CDemoWnd
//////////////////////////////////////////////////////////////////////////
#define MSGHANDLE(nMsg, MsgProc)  {(nMsg), (&CDemoWnd::MsgProc)}

const CDemoWnd::TMSGMAP CDemoWnd::MsgMapTable[] = {
	MSGHANDLE(WM_CREATE,		OnCreate),
	MSGHANDLE(WM_DESTROY,		OnDestroy), 
	MSGHANDLE(WM_PAINT,			OnPaint),
};

CDemoWnd::CDemoWnd(const TCHAR* szAppName)
{
	Create(szAppName, WS_OVERLAPPEDWINDOW, 0, 0, 1280, 720, NULL);
}

CDemoWnd::~CDemoWnd()
{
}

LRESULT	 CDemoWnd::WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	for (int ii = 0; ii < sizeof(MsgMapTable) / sizeof(*MsgMapTable); ii++)
	{
		if (nMsg == MsgMapTable[ii].m_nMsg)
		{
			(this->*MsgMapTable[ii].m_MsgProc)(hWnd, nMsg, wParam, lParam);
			break;
		}
	}

	return __super::FinalWndProc(hWnd, nMsg, wParam, lParam);
}

LRESULT CDemoWnd::OnCreate(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	CenterWindow();

	return 0;
}

LRESULT CDemoWnd::OnDestroy(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	PostQuitMessage(0);

	return 0;
}

LRESULT CDemoWnd::OnPaint(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hDC = BeginPaint(hWnd, &ps);
	
	const UINT nGridCount = 6;
	RECT rtGrids[nGridCount];
	_PartitionGrid(hDC, rtGrids, nGridCount);
 
	int nIndex = 0;
	_DrawDDB(hDC, rtGrids[nIndex++]);

	_DrawBmpRes(hDC, rtGrids[nIndex++]);

	_DrawBmpIndirect(hDC, rtGrids[nIndex++]);

	_DrawDIBitmap(hDC, rtGrids[nIndex++]);

	_DrawDIBSection(hDC, rtGrids[nIndex++]);

	_DrawCompatibleDDB(hDC, rtGrids[nIndex++]);

	EndPaint(hWnd, &ps);

	return 1;
}

//////////////////////////////////////////////////////////////////////////
// following Demo code 
//////////////////////////////////////////////////////////////////////////
void CDemoWnd::_PartitionGrid(HDC hDC, RECT* prtGrids, int nGridCount)
{
	assert(0 < nGridCount);

	//--: Grids rect area
	RECT rtClient;
	GetClientRect(m_hWnd, &rtClient);
	InflateRect(&rtClient, -5, -5);

	//==: calculate every grid rect and paint color
	HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, GetStockObject(DC_BRUSH));
	SetDCBrushColor(hDC, RGB(220, 220, 220));
	Rectangle(hDC, rtClient.left, rtClient.top, rtClient.right, rtClient.bottom);

	RECT rtDemo;
	CopyRect(&rtDemo, &rtClient);
	int nHeight = (rtDemo.bottom - rtDemo.top) / nGridCount;

	for (int ii = 0; ii < nGridCount; ii++)
	{
		int y = rtDemo.top + nHeight * ii;
		SetRect(&prtGrids[ii], rtDemo.left, y, rtDemo.right, y + nHeight);

		Rectangle(hDC, prtGrids[ii].left, prtGrids[ii].top, prtGrids[ii].right, prtGrids[ii].bottom);
	}

	SelectObject(hDC, hOldBrush);

	return;
}

void CDemoWnd::_DrawDDB(HDC hDC, RECT& rtGrid)
{
	UINT nHeight	= rtGrid.bottom - rtGrid.top - 4; 
	UINT nWidth		= nHeight;
	UCHAR Bits[] = {0};
	HBITMAP hBitmap = CreateBitmap(80, 80, 1, 32, (void*)/*&Bits*/NULL);
	
	if (NULL != hBitmap)
	{
		HDC hMemDC = CreateCompatibleDC(hDC);
		HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC, hBitmap);
		BitBlt(hDC, rtGrid.left + 2, rtGrid.top + 2, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
		SelectObject(hMemDC, hOldBmp);
		DeleteObject(hOldBmp); 
	}
	
	return;
}

void CDemoWnd::_DrawBmpRes(HDC hDC, RECT& rtGrid)
{
	HBITMAP hBitmap = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1));
	if (NULL != hBitmap)
	{
		HDC hMemDC = CreateCompatibleDC(hDC);
		HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC, hBitmap);
		BITMAP Bmp;
		GetObject(hBitmap, sizeof(BITMAP), &Bmp);
		BitBlt(hDC, rtGrid.left + 2, rtGrid.top + 2, Bmp.bmWidth, Bmp.bmHeight, hMemDC, 0, 0, SRCCOPY);
		SelectObject(hMemDC, hOldBmp);
		DeleteObject(hOldBmp);
	}
}

void CDemoWnd::_DrawBmpIndirect(HDC hDC, RECT& rtGrid)
{
	BITMAP bm		= {0};
	bm.bmWidth		= 16;
	bm.bmHeight		= 16;
	bm.bmPlanes		= 1;
	bm.bmBitsPixel	= 1;
	bm.bmWidthBytes	= 2;

	BYTE byData[]	= {0x80, 0x01, 0x40, 0x02,
					   0x20, 0x04, 0x10, 0x08,
					   0x08, 0x10, 0x04, 0x20,
					   0x02, 0x40, 0x01, 0x80,
					   0x01, 0x80, 0x02, 0x40,
					   0x04, 0x20, 0x08, 0x10,
					   0x10, 0x08, 0x20, 0x04,
					   0x40, 0x02, 0x80, 0x01};
	bm.bmBits		= byData;
	HBITMAP hBmp = CreateBitmapIndirect(&bm);

	UINT nHeight	= rtGrid.bottom - rtGrid.top - 4; 
	UINT nWidth		= nHeight;
	HDC hMemDC = CreateCompatibleDC(hDC);
	HGDIOBJ hObj = SelectObject(hMemDC, hBmp);
	StretchBlt(hDC, rtGrid.left + 4, rtGrid.top + 4, nWidth - 4, nHeight - 4, hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
	DeleteObject(hBmp);
	DeleteObject(hMemDC);

	return;
}

void CDemoWnd::_DrawDIBitmap(HDC hDC, RECT& rtGrid)
{
	HANDLE hFile = CreateFile(_T("F:\\zTercelWorkStudio\\EveryDayDemo\\Demo0012\\Debug\\24XRGB.bmp"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
	if (INVALID_HANDLE_VALUE != hFile)
	{
		BITMAPFILEHEADER bfh	= {0};
		BITMAPINFO bmi			= {0};
		DWORD dwRead			= 0;
		ReadFile(hFile, (LPVOID)&bfh, sizeof(BITMAPFILEHEADER), &dwRead, NULL);
	
		ReadFile(hFile, (LPVOID)&bmi, bfh.bfOffBits - sizeof(BITMAPFILEHEADER), &dwRead, NULL);
	
		DWORD dwDataSize		= GetFileSize(hFile, NULL) - bfh.bfOffBits;
		UCHAR* pBits			= new UCHAR[dwDataSize];
		ReadFile(hFile, (LPVOID)pBits, dwDataSize, &dwRead, NULL);

		HBITMAP hBitmap			= CreateDIBitmap(hDC, &bmi.bmiHeader, CBM_INIT, pBits, &bmi, DIB_RGB_COLORS);
		
		BITMAP bm;
		GetObject(hBitmap, sizeof(bm), &bm);
		UINT nHeight	= rtGrid.bottom - rtGrid.top - 4; 
		UINT nWidth		= nHeight;
		HDC hMemDC = CreateCompatibleDC(hDC);
		HGDIOBJ hObj = SelectObject(hMemDC, hBitmap);
		StretchBlt(hDC, rtGrid.left + 4, rtGrid.top + 4, nWidth - 4, nHeight - 4, hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
		DeleteObject(hBitmap);
		DeleteObject(hMemDC);

		delete[] pBits;
	}
}

void CDemoWnd::_DrawDIBSection(HDC hDC, RECT& rtGrid)
{
	HANDLE hFile = CreateFile(_T("F:\\zTercelWorkStudio\\EveryDayDemo\\Demo0012\\Debug\\24XRGB.bmp"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
	if (INVALID_HANDLE_VALUE != hFile)
	{
		BITMAPFILEHEADER bfh	= {0};
		BITMAPINFO bmi			= {0};
		DWORD dwRead			= 0;
		ReadFile(hFile, (LPVOID)&bfh, sizeof(BITMAPFILEHEADER), &dwRead, NULL);

		ReadFile(hFile, (LPVOID)&bmi, bfh.bfOffBits - sizeof(BITMAPFILEHEADER), &dwRead, NULL);

		DWORD dwDataSize		= GetFileSize(hFile, NULL) - bfh.bfOffBits;
		UCHAR* pBits1			= new UCHAR[dwDataSize];
		ReadFile(hFile, (LPVOID)pBits1, dwDataSize, &dwRead, NULL);

		UCHAR* pBits			= NULL;	
		HBITMAP hBitmap			= CreateDIBSection(hDC, (const BITMAPINFO*)&bmi.bmiHeader, DIB_RGB_COLORS, (LPVOID*)&pBits, NULL, 0);
		memcpy(pBits, pBits1, dwDataSize);

		BITMAP bm;
		GetObject(hBitmap, sizeof(bm), &bm);
		UINT nHeight	= rtGrid.bottom - rtGrid.top - 4; 
		UINT nWidth		= nHeight;
		HDC hMemDC = CreateCompatibleDC(hDC);
		HGDIOBJ hObj = SelectObject(hMemDC, hBitmap);
		StretchBlt(hDC, rtGrid.left + 4, rtGrid.top + 4, nWidth - 4, nHeight - 4, hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
		DeleteObject(hBitmap);
		DeleteObject(hMemDC);

		delete[] pBits1;
	}
}

void CDemoWnd::_DrawCompatibleDDB(HDC hDC, RECT& rtGrid)
{
	UINT nHeight	= rtGrid.bottom - rtGrid.top - 4; 
	UINT nWidth		= nHeight;

	HBITMAP hBitmap = CreateCompatibleBitmap(hDC, nWidth, nHeight);
	HDC hMemDC		= CreateCompatibleDC(hDC);
	HGDIOBJ hGDIObj = SelectObject(hMemDC, hBitmap);
	
	BitBlt(hDC, rtGrid.left, rtGrid.top, rtGrid.right - rtGrid.left, rtGrid.bottom - rtGrid.top, hMemDC, 0, 0, SRCCOPY);

	SelectObject(hMemDC, hGDIObj);
	DeleteObject(hMemDC);
	DeleteObject(hBitmap);
	
	return;
}